﻿/*-------------------------------------------------------------------------
 * CLR版本:     4.0.30319.42000
 * 创建人:      song
 * 创建时间：   2024/4/9 17:56:20
 * 功 能：      自动绘制按钮特性
 *-------------------------------------------------------------------------*/

using System;
using UnityEngine;

namespace Function.SerializedPropertyAttribute
{
    [AttributeUsage(AttributeTargets.Method)]
    public class ButtonMethodAttribute : PropertyAttribute
    {
    }
}

#if UNITY_EDITOR
namespace Function.SerializedPropertyAttribute
{
    using Object = UnityEngine.Object;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using UnityEditor;

    public class ButtonMethodHandler
    {
        private List<MethodInfo> _methods; //自动特性的方法
        private readonly Object _target;

        public ButtonMethodHandler(Object target)
        {
            _target = target;
            _methods = CollectValidMembers(_target.GetType());
        }


        private static bool IsButtonMethod(MemberInfo memberInfo)
        {
            return Attribute.IsDefined(memberInfo, typeof(ButtonMethodAttribute));
        }

        private static bool IsValidMember(MethodInfo method, MemberInfo member)
        {
            if (method == null)
            {
                string.Format(
                    "Property <color=brown>{0}</color>.Reason: Member is not a method but has EditorButtonAttribute!",
                    member.Name).Warn();
                return false;
            }

            if (method.GetParameters().Length > 0)
            {
                string.Format(
                    "Method <color=brown>{0}</color>.Reason: Methods with parameters is not supported by EditorButtonAttribute!",
                    method.Name).Warn();
                return false;
            }

            return true;
        }

        public static string SplitCamelCase(string camelCaseString)
        {
            if (string.IsNullOrEmpty(camelCaseString)) return camelCaseString;

            var camelCase = Regex.Replace(Regex.Replace(camelCaseString, @"(\P{Ll})(\P{Ll}\p{Ll})", "$1 $2"),
                @"(\p{Ll})(\P{Ll})", "$1 $2");
            var firstLetter = camelCase.Substring(0, 1).ToUpper();

            if (camelCaseString.Length > 1)
            {
                var rest = camelCase.Substring(1);

                return firstLetter + rest;
            }

            return firstLetter;
        }

        public static void InvokeMethod(UnityEngine.Object target, MethodInfo method)
        {
            var result = method.Invoke(target, null);

            if (result != null)
            {
                var message = string.Format("{0} \nResult of Method '{1}' invocation on object {2}", result,
                    method.Name, target.name);
            }
        }

        public static List<MethodInfo> CollectValidMembers(Type type)
        {
            List<MethodInfo> methods = null;

            var members = type.GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public |
                                          BindingFlags.NonPublic)
                .Where(IsButtonMethod);

            foreach (var member in members)
            {
                var method = member as MethodInfo;
                if (IsValidMember(method, member))
                {
                    if (methods == null) methods = new List<MethodInfo>();
                    methods.Add(method);
                }
            }

            return methods;
        }

        public void OnInspectorGUI()
        {
            if (_methods == null)
                return;
            EditorGUILayout.Space();
            foreach (var method in _methods)
                if (GUILayout.Button(SplitCamelCase(method.Name)))
                    InvokeMethod(_target, method);
        }
    }
}
#endif